`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company:
// Engineer:
//
// Create Date: 2022/03/10 19:12:29
// Design Name:
// Module Name: controller
// Project Name:
// Target Devices:
// Tool Versions:
// Description:
//
// Dependencies:
//
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//
//////////////////////////////////////////////////////////////////////////////////
module controller(
        input wire [31:0] inst,
        output wire jump,                   //无条件跳转信号
        branch,                             // 条件跳转信号
        alu_a_src,                          //二路选择器srcA选择信号
        memtoreg,                           //结果选择信号
        memwrite,                           //存储器写使能
        regwrite,                           //寄存器写使能
        output wire [1:0] alu_b_src,        //aluB口选择信号
        output wire [2:0] extop,            //扩展器操作控制信号
        output wire [3:0] alu_ctr           //alu运算控制信号
    );

    wire [6:0] opcode = inst[6:0];
    wire [2:0] funct3 = inst[14:12];

    parameter [6:0] op_R_type = 7'h33;
    parameter [6:0] op_I_type_load	= 7'h03;
    parameter [6:0] op_I_type_alu	= 7'h13;
    parameter [6:0] op_I_type_jump	= 7'h6F;
    parameter [6:0] op_S_type = 7'h23;
    parameter [6:0] op_B_type = 7'h63;
    parameter [6:0] op_U_type_load	= 7'h37;

    assign branch = opcode == op_B_type;                // B-type

    assign jump = opcode == op_I_type_jump ;            // Jump

    assign alu_a_src = opcode == op_I_type_jump;        // Jump

    assign memtoreg = opcode == op_I_type_load;         // load

    assign regwrite = ( opcode == op_R_type )
           | ( opcode == op_I_type_alu)
           | ( opcode == op_U_type_load )
           | ( opcode == op_I_type_load )
           | ( opcode == op_I_type_jump );               // R-type / I-alu / lui / load / Jump

    assign memwrite = (opcode == op_S_type);               // S-type

    assign alu_ctr[3] = ( opcode == op_U_type_load )                // lui / B-type
           | ( opcode == op_B_type );

    assign alu_ctr[2] = (( opcode == op_R_type )                    // R-type / I-alu / lui
                         | ( opcode == op_I_type_alu )) & funct3[2]
           | ( opcode == op_U_type_load) ;

    assign alu_ctr[1] = (( opcode == op_R_type )
                         | ( opcode == op_I_type_alu )) & funct3[1]
           | ( opcode == op_U_type_load) ;

    assign alu_ctr[0] = (( opcode == op_R_type )
                         | ( opcode == op_I_type_alu )) & funct3[0]
           | ( opcode == op_U_type_load) ;

    assign alu_b_src[1] = ( opcode == op_I_type_alu)
           | ( opcode == op_I_type_load)
           | ( opcode == op_U_type_load)
           | ( opcode == op_S_type);

    assign alu_b_src[0] = ( opcode == op_I_type_jump);

    assign extop[2] = ( opcode == op_I_type_jump);
    assign extop[1] = ( opcode == op_S_type) | ( opcode == op_B_type);
    assign extop[0] = ( opcode == op_U_type_load) | ( opcode == op_B_type);


endmodule
